#include <math.h>
#include <stdio.h>
#include "common.h"
#include "player.h"
#include "background.h"
#include "particle.h"

// These are for testing purposes
int Particle::colLost = 0;
int Particle::colCount = 0;


Particle::Particle(class PhysicsModule *phys, int c, double* pos, double* vel)
{
	killMe = 0;
	activateDelay = 0.0;
	
	color = c;
	g = phys->addGravitated(pos,vel,PARTICLE_MASS, PARTICLE, this);
}

Particle::traceback Particle::tracebackCollision(Background *back, double compression)
{
	traceback t;
	int count;
	double xcur,ycur, xit,yit;
	
	// Along the line in 1-pixels steps
	// First scale velocity to a normal (and reverse direction)
	double length;
	length = sqrt(g->velocity[0]*g->velocity[0]+g->velocity[1]*g->velocity[1]);
	xit = -g->velocity[0]/length;
	yit = -g->velocity[1]/length;
	
	xcur = g->position[0];
	ycur = g->position[1];
	
	// Iterate for 'count' number of pixels
	count = int(35.0*compression); // Repeat at least this many times
	do {
		xcur += xit;
		ycur += yit;
		
		t.newx = int(xcur);
		t.newy = int(ycur);
		count--;
	}while(back->testCollision(t.newx,t.newy) && count>0);
	
	return t;
}

void Particle::collideBackground(Background *back, double delta)
{
	int colTypeUpd = 0;
	traceback t;
	
	//if(activateDelay > 0.0) activateDelay -= delta; // Eiffel tower effect for everyone \o/
	if(/*activateDelay <= 0.0 && */back->testCollision(g->position[0],g->position[1]) || back->getZones()->size() == 0) {
		killMe = 1; // Ask the particle [politely] to be destroyed
		colCount++;
		colTypeUpd = 1;
		
		// Freeze particle onto the background
		
		// An alternate [faster] implementation would be to trace a line from the point of impact
		// towards its velocity vector: Then repeat until free.. This should be much faster and require
		// less [complex/slow] mathematics
		t = tracebackCollision(back, delta*FPS);
		
		// New and improved!
		// And hellofalot slower :D
		int minx,miny;
		int maxcol;
		maxcol = 0;
		minx = t.newx;
		miny = t.newy;
		// Might be optimized: Currently it takes 3^2*(3^2)=81 iterations to finish the test. Maybe short ciruit when maxcol > some num?
		for(int x=t.newx-1; x<=t.newx+1; x++) {
			for(int y=t.newy-1; y<=t.newy+1; y++) {
				// For each free square that exists in this range
				if(!back->testCollision(x,y)) {
					int cols = 0;
					
					// Count the number of adjacent pixels
					for(int ix=x-1; ix<=x+1; ix++) {
						for(int iy=y-1; iy<=y+1; iy++) {
							// Count the number of collisions
							if(back->testCollision(ix,iy)) {
								cols++;
							}
						}
					}
					
					// If the number of adjacent pixels are the highest, make it active
					if(cols > maxcol) {
						minx = x;
						miny = y;
						maxcol = cols;
						
						//if(maxcol >= 4) goto short_circuit;
						// Might be a negligible slowdown, at least compared to the above algorithm
					}
				}
			}
		}
			// GOTO!
			//short_circuit:
		if(!back->testCollision(minx,miny))
			back->freezeParticle(minx,miny, g->t.p->color);
		else colLost++;
		
		if(back->getZones()->size()==0) back->updateAll();
	}

	if(colTypeUpd && (colCount%100000)==0)
		printf("Collision count=%d, Lost=%d (%.1f%%)\n", colCount, colLost, double(colLost)/(double(colCount))*100.0);
	
}

void Particle::collidePlayer(Player *p)
{
	p->damage(1); // Ouch!
	killMe = 1;
}

